﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Net;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Linq;

namespace 一键nuget发布
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            txtPackagePath.Text = System.Configuration.ConfigurationManager.AppSettings["packagePath"];
            txtWebHost.Text = System.Configuration.ConfigurationManager.AppSettings["webHost"];
            txtPublicKey.Text = System.Configuration.ConfigurationManager.AppSettings["publicKey"];
            lblProcessBar.Text = "";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                button1.Enabled = false;
                var list = GetNugetPackList();


                new System.Threading.Thread(() =>
                {

                    for (var i = 1; i <= list.Count; i++)
                    {
                        try
                        {
                            var item = list[i - 1];

                            var isExist = CheckIsExists(item);
                            if (isExist)
                            {
                                this.Invoke(new Action(() =>
                                {
                                    this.progressBar1.Value = Math.Min((int)(i * 100 / list.Count), 100);
                                    this.lblProcessBar.Text = $"{i}/{list.Count} 已存在 {item}";
                                }));
                                continue;
                            }
                            PublishItem(item);
                            this.Invoke(new Action(() =>
                            {
                                this.progressBar1.Value = Math.Min((int)(i * 100 / list.Count), 100);
                                this.lblProcessBar.Text = $"{i}/{list.Count} {item}";
                            }));
                        }
                        catch (Exception ex)
                        {
                            var msg = ex.Message;
                            while (ex.InnerException != null)
                            {
                                ex = ex.InnerException;
                                msg = ex.Message;
                            }
                            MessageBox.Show(msg);
                        }
                    }
                    this.Invoke(new Action(() =>
                    {
                        button1.Enabled = true;
                        MessageBox.Show("上传完成");
                    }));

                }).Start();
            }
            catch (Exception ex)
            {
                var msg = ex.Message;
                while (ex.InnerException != null)
                {
                    ex = ex.InnerException;
                    msg = ex.Message;
                }
                MessageBox.Show(msg);
            }
        }


        public bool PublishItem(string nupkgPath)
        {
            var cmdStr = $"push {nupkgPath} {txtPublicKey.Text} -Source {txtWebHost.Text}";

            var fileName = AppDomain.CurrentDomain.BaseDirectory + "nuget.exe";
            bool result = false;
            try
            {
                using (Process myPro = new Process())
                {

                    myPro.StartInfo.FileName = fileName;
                    myPro.StartInfo.Arguments = cmdStr;
                    myPro.StartInfo.CreateNoWindow = true;
                    myPro.StartInfo.UseShellExecute = false;    //是否使用操作系统shell启动
                    myPro.ErrorDataReceived += new DataReceivedEventHandler((obj, e) =>
                    {

                    });

                    myPro.OutputDataReceived += new DataReceivedEventHandler((obj, e) =>
                    {

                    });

                    myPro.Start();
                    //如果调用程序路径中有空格时，cmd命令执行失败，可以用双引号括起来 ，在这里两个引号表示一个引号（转义）

                    myPro.WaitForExit();

                    myPro.Close();//关闭进程
                    myPro.Dispose();//释放资源
                    result = true;
                }
            }
            catch (Exception e)
            {
                result = false;
            }
            return result;
        }

        public bool CheckIsExists(string nupkgPath)
        {
            var fileName = System.IO.Path.GetFileNameWithoutExtension(nupkgPath);
            var version = new System.Text.RegularExpressions.Regex("\\d+[\\d\\.]+$").Match(fileName).Value;

            if (string.IsNullOrWhiteSpace(version))
                return false;

            var packageName = fileName.Replace(version, "").Trim('.');

            var uri = new Uri(txtWebHost.Text);
            var host = $"{uri.Scheme}://{uri.Authority}";

            var requestUrl = $"{host}/nuget/Search()?$filter=IsLatestVersion&searchTerm={System.Web.HttpUtility.UrlEncode("'" + packageName + "'")}&includePrerelease=false&$skip=0&$top=26";

            var res = HttpGet(requestUrl);

            XmlDocument doc = new XmlDocument();
            doc.LoadXml(res);

            var entrys = doc.GetElementsByTagName("entry");
            if (entrys == null || entrys.Count <= 0)
            {
                return false;
            }

            foreach (var obj in entrys)
            {
                var item = obj as System.Xml.XmlElement;
                var childNodes = item.ChildNodes;

                foreach (var obj2 in childNodes)
                {
                    var item2 = obj2 as XmlElement;

                    if (item2.Name.ToLower() == "title")
                    {
                        if (item2.InnerText.ToLower() != packageName.ToLower())
                        {
                            continue;
                        }
                    }
                    if (item2.Name.ToLower() == "m:properties")
                    {
                        foreach (var obj3 in item2.ChildNodes)
                        {
                            var item3 = obj3 as XmlElement;
                            if (item3.Name.ToLower() == "d:Version".ToLower())
                            {
                                if (item3.InnerText == version)
                                {
                                    return true;
                                }
                            }
                        }
                    }
                }
            }

            return true;
        }

        public List<string> GetNugetPackList()
        {
            var packagesPath = txtPackagePath.Text;

            var nupkgList = new List<string>();

            //C#遍历指定文件夹中的所有文件 
            var TheFolder = new DirectoryInfo(packagesPath);

            var files = TheFolder.GetFiles("*.nupkg", SearchOption.AllDirectories);

            if (files != null && files.Length > 0)
            {
                foreach (var item in files)
                {
                    nupkgList.Add(item.FullName);
                }
            }

            return nupkgList;
        }

        public string HttpGet(string Url)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
            request.Method = "GET";
            request.ContentType = "text/html;charset=UTF-8";

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream myResponseStream = response.GetResponseStream();
            StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
            string retString = myStreamReader.ReadToEnd();
            myStreamReader.Close();
            myResponseStream.Close();

            return retString;
        }
    }
}
